import django.utils.timezone as timezone
from django.conf import settings
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token

__all__ = [
    "Application",
    "ApplicationTag",
    "Environment",
    "Business",
    "PublicColumns",
    "Instances",
    "Language",
]


@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)


APP_TYPE_CHOICES = ((1, "java"), (2, "node"), (3, "html"))

INSTANCES_STATUS_CHOICES = ((1, "running"), (2, "stopped"), (3, "terminate"))


class PublicColumns(models.Model):
    created_by = models.CharField(max_length=32, blank=True, default="sys")
    created_at = models.DateTimeField(default=timezone.now)
    updated_by = models.CharField(max_length=32, blank=True, default="sys")
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True


class Business(PublicColumns):
    name = models.CharField(max_length=64, unique=True, null=False, blank=False)

    def __str__(self):
        return self.name

    class Meta:
        db_table = "cmdb_business"


class Environment(PublicColumns):
    name = models.CharField(max_length=64, null=False, blank=False)
    private_ip = models.CharField(max_length=64, null=False, blank=False)
    business = models.ForeignKey(Business, on_delete=models.CASCADE, to_field="name")
    instances = models.CharField(max_length=64, null=False, blank=False, default=None)
    public_ip = models.CharField(max_length=64, null=True, blank=True, default=None)

    def __unicode__(self):
        return "{}-{}".format(self.business, self.name)

    def __str__(self):
        return self.__unicode__()

    class Meta:
        db_table = "cmdb_environment"
        unique_together = (
            "name",
            "business",
        )


class Language(PublicColumns):
    name = models.CharField(max_length=32, unique=True, null=False, blank=False)
    base_image = models.CharField(max_length=128, null=False, blank=False)
    jvm_opts = models.CharField(max_length=512, null=True, blank=True)
    run_base_path = models.CharField(max_length=32, default="/data")
    gc_opts = models.CharField(max_length=512, null=True, blank=True)
    metrics_port = models.IntegerField(default=54321)
    metrics_path = models.CharField(max_length=32, default="/prometheus")

    def __unicode__(self):
        return "{}".format(self.name)

    def __str__(self):
        return self.__unicode__()

    class Meta:
        db_table = "cmdb_language"


class Resource(PublicColumns):
    name = models.CharField(max_length=32, unique=True, null=False, blank=False)
    limit_memory = models.CharField(max_length=16, null=True, blank=True)
    limit_cpu = models.CharField(max_length=16, null=True, blank=True)
    request_memory = models.CharField(max_length=16, null=True, blank=True)
    request_cpu = models.CharField(max_length=16, null=True, blank=True)

    def __unicode__(self):
        return "{}".format(self.name)

    def __str__(self):
        return self.__unicode__()

    class Meta:
        db_table = "cmdb_resource"


class Application(PublicColumns):
    name = models.CharField(max_length=64, null=False, blank=False)
    desc = models.TextField(max_length=256, null=True, blank=True)
    language = models.ForeignKey(
        Language, on_delete=models.CASCADE, to_field="name", default="java"
    )
    jvm_opts = models.CharField(max_length=512, null=True, blank=True)
    resource = models.ForeignKey(
        Resource, on_delete=models.CASCADE, to_field="name", default="medium"
    )
    path = models.CharField(max_length=64, default="/")
    health = models.CharField(
        max_length=64, null=True, blank=True, default="/system/version"
    )
    post_start = models.CharField(max_length=64, null=True, blank=True)
    pre_stop = models.CharField(max_length=64, null=True, blank=True)
    port = models.IntegerField(default=8000)
    image = models.CharField(max_length=256, null=False, blank=False)
    domain = models.CharField(max_length=128, null=True, blank=True)
    svc = models.BooleanField(null=False, blank=False, default=False)
    metrics = models.BooleanField(null=False, blank=False, default=False)
    initial_delay_seconds = models.IntegerField(default=60)
    business = models.ForeignKey(Business, on_delete=models.CASCADE, to_field="name")

    def __unicode__(self):
        return "{}-{}".format(self.business, self.name)

    def __str__(self):
        return self.__unicode__()

    class Meta:
        db_table = "cmdb_application"
        # unique_together = ('business', 'name')
        unique_together = ("business", "name", "language")


class ApplicationTag(PublicColumns):
    application = models.ForeignKey(Application, related_name="tags")
    tag = models.CharField(max_length=32)

    class Meta:
        db_table = "cmdb_application_tag"
        unique_together = (
            "application",
            "tag",
        )


class Instances(PublicColumns):
    name = models.CharField(max_length=64, null=True, blank=True)
    owner = models.CharField(max_length=32, null=True, blank=True)
    instance_id = models.CharField(max_length=64, unique=True, null=True, blank=False)
    instance_type = models.CharField(max_length=32, null=True, blank=False)
    launch_time = models.DateTimeField(default=timezone.now)
    key_name = models.CharField(max_length=64, null=False, blank=True, default="devops")
    status = models.IntegerField(choices=INSTANCES_STATUS_CHOICES, default=1)
    private_ip = models.CharField(max_length=32, null=False, blank=False)
    public_ip = models.CharField(max_length=32, null=True, blank=True)
    security_ids = models.CharField(max_length=128, null=True, blank=True)
    subnet_id = models.CharField(max_length=32, null=True, blank=True)
    vpc_id = models.CharField(max_length=64, null=True, blank=True)
    availability_zone = models.CharField(max_length=64, null=True, blank=True)

    def __unicode__(self):
        return "{}".format(self.name)

    def __str__(self):
        return self.__unicode__()

    class Meta:
        db_table = "cmdb_instances"
